package com.github.m6d21.sso.support.annotation;

import com.github.m6d21.sso.common.util.DateUtil;
import com.github.m6d21.sso.core.exception.BusinessException;
import com.github.m6d21.sso.support.enums.StatusCode;
import java.text.ParseException;
import java.util.Date;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
 *<p>
 *
 *</p>
 *
 * @author liuyang
 * @date 2018/12/18 Tue 21:57:00
 * @since 1.0.0
 */
public class DateArgumentResolver implements HandlerMethodArgumentResolver {

    private static final Logger LOG = LoggerFactory.getLogger(DateArgumentResolver.class);

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        //参数上包含DateParam注解，并且参数类型是日期
        return parameter.hasParameterAnnotation(RequestDateParam.class)
            && parameter.getParameterType() == Date.class;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        HttpServletRequest httpServletRequest = webRequest.getNativeRequest(HttpServletRequest.class);

        RequestDateParam dateParam = parameter.getParameterAnnotation(RequestDateParam.class);
        Date date = null;
        String pattern = dateParam.format();
        String parameterName = getParameterName(parameter);
        String value = httpServletRequest.getParameter(parameterName);
        if (value != null) {
            if (StringUtils.isNotEmpty(pattern)) {
                try {
                    date = DateUtil.parse(value, pattern);
                } catch (ParseException e) {
                    LOG.error("格式化日期失败, 日期:{}, 正确格式:{}", value, pattern);
                }
            }
            if (date == null) {
                try {
                    date = DateUtil.parse(value, Locale.US);
                } catch (Exception e) {
                    LOG.error("格式化日期失败, 日期:{}, 格式:{},error:{}", value, pattern, e);
                    throw new BusinessException(StatusCode.REQUEST_PARAM_ERROR.getCode(),
                        "日期格式有误,日期:" + value + ", 正确格式:" + pattern);
                }
            }
        } else {
            resolveRequired(parameter);
        }
        return date;
    }

    private String getParameterName(MethodParameter parameter) {
        RequestDateParam requestDateParam = parameter.getParameterAnnotation(RequestDateParam.class);
        String parameterName = requestDateParam.value();
        if (StringUtils.isEmpty(parameterName)) {
            parameterName = parameter.getParameterName();
        }
        return parameterName;
    }

    private void resolveRequired(MethodParameter parameter) throws Exception {
        RequestDateParam requestDateParam = parameter.getParameterAnnotation(RequestDateParam.class);
        if (requestDateParam.required()) {
            throw new MissingServletRequestParameterException(getParameterName(parameter), "String");
        }
    }
}
